<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        /* 一、call()方法和apply()方法
            作用：改变函数中this的指向
            这两者都是函数对象的方法，需要通过函数对象来调用
            当对函数调用call()和apply()都会调用函数执行
        */
        var obj = {
            name: "小明"
        };
        var obj2 = {
            name:"小红"
        }
        function fun(){
            console.log(this.name);
        }
        fun.call(obj); // obj
        fun.call(obj2); // obj2

        /* 
            在调用call()和apply()可以将一个对象指定为第一个参数，
            此时这个对象将会成为函数执行时的this

            二者的区别：
                call方法可以将实参在对象之后依次传递
                apply方法需要将实参封装到一个数组中统一传递
        */
        function fun(a, b){
            console.log("a = " + a + ", b = " + b);
        }
        fun.call(obj, 2, 3); // a = 2, b = 3
        fun.apply(obj, [2, 3]); // a = 2, b = 3

        /* this的情况：
            1.以函数的形式调用时，this永远指向window
            2.以方法的形式调用时，this指向调用方法的对象
            3.以构造函数的形式调用时，this指向新创建的对象
            4.以call和apply的形式调用时，this指向指定的那个对象
        */

        /* 二、arguments
            在调用函数时，浏览器每次都会传递进两个隐含的参数：
                1.函数的上下文对象：this
                2.封装实参的对象：arguments
            arguments是一个类数组对象（并非数组），可以通过索引来操作数据，也可以获取长度

        */
        function fun1(){
            console.log(arguments instanceof Array); // false
            console.log(Array.isArray(arguments));   // false
        }
        fun1();

        /* 
            在调用函数时，我们所传递的实参都会在arguments中保存
            我们即使不定义形参，也可以通过arguments来使用（接收）实参，只不过比较麻烦
                1.arguments[0]表示第一个实参
                2.arguments[1]表示第二个实参
        */
        function fun2(a,b,c){
            console.log("arguments.length = " + arguments.length + ", arguments[0] = " + arguments[0]); 
        }
        fun2("hello"); // arguments.length = 1, arguments[0] = hello
        fun2(true, "hello"); // arguments.length = 2, arguments[0] = true

        // 它里边有一个属性叫做callee，这个属性对应一个函数对象，就是当前正在执行的函数对象
        function fun3(){
            console.log(arguments.callee);
            // function fun3(){
            //     console.log(arguments.callee);
            // }
            console.log(arguments.callee == fun3); // true
        }
        fun3();
    </script>
</head>
<body>
    
</body>
</html>